// GDT初始化
use crate::system::sysdef::{GDT_BASE, TSS_DESC, ESP0_IDX, SS0_IDX, TSS_SIZE, TSS};
use crate::process::task::PROCESS;

// =========================
// 内部数据定义
const KERNEL_CS: u32 = 0x1;         // 内核代码段选择符
const KERNEL_DS: u32 = 0x2;         // 内核数据段选择符
const KERNEL_STACK: u32 = 0x3;      // 内核堆栈段选择符

extern "C" {
    fn print_str_endwith_enter(p : *const u8, l : u32);
    fn reload_segment_registers();
}

// GDT描述符表初始化
pub fn gdt_init() {   
    gdt_desc_entry_init(0, 0, 0, 0);                                // GDT表第0项全部为0，保留
    gdt_desc_entry_init(KERNEL_CS, 0, 0x000FFFFF, 0xC09A);          // GDT表第1项:代码段 00CF 9A00 0000 FFFF
    gdt_desc_entry_init(KERNEL_DS, 0, 0x000FFFFF, 0xC093);          // GDT表第2项:数据段 00CF 9300 0000 FFFF
    gdt_desc_entry_init(KERNEL_STACK, 0, 0x000FFFF, 0xC093);        // GDT表第3项:堆栈段 00C0 9300 0000 FFFF

    // 暂时使用一个全局的TSS
    // TODO：后续考虑是否每个任务使用单独的TSS
    const TEMP_STACK_TOP:u32 = 0x404000; // 临时堆栈栈顶
    unsafe {
        TSS_DESC.tss[ESP0_IDX] = TEMP_STACK_TOP;
        TSS_DESC.tss[SS0_IDX] = (KERNEL_STACK * 8) & 0xFF;
    }
    gdt_desc_entry_init(4, unsafe {&TSS_DESC as *const TSS as u32}, (TSS_SIZE * 4 - 1) as u32, 0x0089); // 32位TSS段
    
    unsafe {
        reload_segment_registers();         // 重新加载段寄存器
        let _dispstr = "GDT init ok.";
        print_str_endwith_enter(_dispstr.as_ptr(), _dispstr.len().try_into().unwrap());
    }
}

// GDT描述符表项初始化
pub fn gdt_desc_entry_init(idx : u32, seg_base : u32, seg_limit : u32, seg_attribute : u16) {
    let gdt_entry_addr = (GDT_BASE + idx * 8) as *mut u8;
    unsafe {
        *gdt_entry_addr.offset(0) = (seg_limit & 0xFF) as u8;               // 段界限bit 0-7
        *gdt_entry_addr.offset(1) = ((seg_limit >> 8) & 0xFF) as u8;        // 段界限bit 8-15
        *gdt_entry_addr.offset(2) = (seg_base & 0xFF) as u8;                // 段基址bit 0-7
        *gdt_entry_addr.offset(3) = ((seg_base >> 8) & 0xFF) as u8;         // 段基址bit 8-15
        *gdt_entry_addr.offset(4) = ((seg_base >> 16) & 0xFF) as u8;        // 段基址bit 16-23
        *gdt_entry_addr.offset(5) = (seg_attribute & 0xFF) as u8;           // 段属性bit 0-7
        *gdt_entry_addr.offset(6) = ((seg_limit >> 16) & 0x0F) as u8;       // bit0-3对应 段界限bit 16-19
        *gdt_entry_addr.offset(6) += ((seg_attribute >> 8) & 0xF0) as u8;   // bit4-7对应 段属性bit 12-15
        *gdt_entry_addr.offset(7) = ((seg_base >> 24) & 0xFF) as u8;        // 段基址bit 24-31
    }
}

// LDT描述符表项初始化
pub fn ldt_desc_entry_init(nr: usize, idx : u32, seg_base : u32, seg_limit : u32, seg_attribute : u16) {
    unsafe {
        let p = PROCESS[nr].as_mut();
        let ldt_entry_addr = (p.unwrap().ldts.as_ptr() as u32 + idx * 8) as *mut u8;

        *ldt_entry_addr.offset(0) = (seg_limit & 0xFF) as u8;               // 段界限bit 0-7
        *ldt_entry_addr.offset(1) = ((seg_limit >> 8) & 0xFF) as u8;        // 段界限bit 8-15
        *ldt_entry_addr.offset(2) = (seg_base & 0xFF) as u8;                // 段基址bit 0-7
        *ldt_entry_addr.offset(3) = ((seg_base >> 8) & 0xFF) as u8;         // 段基址bit 8-15
        *ldt_entry_addr.offset(4) = ((seg_base >> 16) & 0xFF) as u8;        // 段基址bit 16-23
        *ldt_entry_addr.offset(5) = (seg_attribute & 0xFF) as u8;           // 段属性bit 0-7
        *ldt_entry_addr.offset(6) = ((seg_limit >> 16) & 0x0F) as u8;       // bit0-3对应 段界限bit 16-19
        *ldt_entry_addr.offset(6) += ((seg_attribute >> 8) & 0xF0) as u8;   // bit4-7对应 段属性bit 16-19
        *ldt_entry_addr.offset(7) = ((seg_base >> 24) & 0xFF) as u8;        // 段基址bit 24-31
    }
}

#[no_mangle]
pub extern "C" fn get_ldt_addr(nr: usize) -> u32 {
    unsafe {
        let p = PROCESS[nr].as_mut();
        p.unwrap().ldts.as_ptr() as u32
    } 
}